# -*- coding: UTF-8 -*-
from mutator import blobmuta
from mutator import stringmuta
from mutator import binarymuta
import random
import bluetooth

class Sdp:

    PDU_ID = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07']

    TRANSACTION_ID = '\x00\x00' # 标识传送次数

    PARAMETER_LENGTH = '\x00\x0f' # 负载长度

    PARAMETERS = '\x35\x03\x19\x10\x02\xff\xff\x35\x05\x0a\x00\x00\xff\xff\x00' # 负载参数

    def __init__(self, addr):
        self.addr = addr

    def send_sdp(self, msg):
        psm = 1
        sock = bluetooth.BluetoothSocket(bluetooth.L2CAP)
        try:
            sock.connect((self.addr, psm))
        except:
            return 1
        sock.settimeout(2)
        try:
            # 同一个包发5次
            for i in range(0, 5):
                sock.send(msg)
        except:
            return 2
        return 0

    # 随机选择pdu，对负载进行变异
    def fuzz_params(self):
        source_params = '\x35\x03\x19\x10\x02\xff\xff\x35\x05\x0a\x00\x00\xff\xff\x00'
        r_flag = random.randint(1, 12)
        r_id = self.PDU_ID[random.randint(0, 7)]
        rand = random.Random()
        fuzz_params = self._fs(source_params, rand, r_flag)
        msg = r_id + '\x00\x00\x00\x0f' + fuzz_params
        r_code = self.send_sdp(msg)
        return [r_code, r_flag, msg]
        # return [r_code, r_flag, r_id, fuzz_params, msg]

    # 随机选择pdu，然后对pdu进行fuzz
    def fuzz_pud_id(self):
        r_id = self.PDU_ID[random.randint(0, 7)]
        rand = random.Random()
        r_flag = random.randint(1, 12)
        fuzz_pud = self._fs(r_id, rand, r_flag)
        msg = fuzz_pud + '\x00\x00\x00\x0f' + self.PARAMETERS
        r_code = self.send_sdp(msg)
        return [r_code, r_flag, msg]
        # return [r_code, r_flag, r_id, fuzz_pud, msg]

    # 随机选择pdu,然后对TRANSACTION_ID进行fuzz
    def fuzz_transcation_id(self):
        r_id = self.PDU_ID[random.randint(0, 7)]
        rand = random.Random()
        r_flag = random.randint(1, 12)
        fuzz_tra = self._fs(self.TRANSACTION_ID, rand, r_flag)
        msg = r_id + fuzz_tra + '\x00\x0f' + self.PARAMETERS
        r_code = self.send_sdp(msg)
        return [r_code, r_flag, msg]
        # return [r_code, r_flag, r_id, fuzz_tra, msg]

    # 随机选择pdu,然后对PARAMETER_LENGTH进行fuzz
    def fuzz_parameter_length(self):
        r_id = self.PDU_ID[random.randint(0, 7)]
        rand = random.Random()
        r_flag = random.randint(1, 12)
        fuzz_pal = self._fs(self.PARAMETER_LENGTH, rand, r_flag)
        msg = r_id + '\x00\x00' + fuzz_pal + self.PARAMETERS
        r_code = self.send_sdp(msg)
        return [r_code, r_flag, msg]
        # return [r_code, r_flag, r_id, fuzz_pal, msg]

    # 随机选择pdu,然后对整个进行fuzz
    def fuzz_all(self):
        r_id = self.PDU_ID[random.randint(0, 7)]
        rand = random.Random()
        r_flag = random.randint(1, 12)
        msg = r_id + '\x00\x00\x00\x0f' + self.PARAMETERS
        fuzz_msg = self._fs(msg, rand, r_flag)
        r_code = self.send_sdp(fuzz_msg)
        return [r_code, r_flag, msg]
        # return [r_code, r_flag, r_id, fuzz_msg, msg]

    def _fs(self, data, rand, flag):

        if (flag == 0):
            return data

        if (flag == 1):
            s = stringmuta.StringCaseMutator()
            return s.mutationRandomCase(data)

        if (flag == 2):
            s = stringmuta.UnicodeBomMutator()
            return s.randomMutation(rand)

        if (flag == 3):
            s = stringmuta.UnicodeBadUtf8Mutator()
            return s.randomMutation(rand)

        if (flag == 4):
            b = blobmuta.DWORDSliderMutator(data)
            return b.randomMutation(data, rand)

        if (flag == 5):
            b = blobmuta.BitFlipperMutator(data)
            return b.randomMutation(data, rand)

        b = blobmuta.BlobMutator(data)
        if (flag == 6):
            return ""  # 返回空字符串

        if (flag == 7):
            return b.changeReduceBuffer(data, rand)

        if (flag == 8):
            return b.changeChangeRangeSpecial(data, rand)

        if (flag == 9):
            return b.changeExpandBuffer(data, rand)

        if (flag == 10):
            return b.changeNullRange(data, rand)

        if (flag == 11):
            return b.changeChangeRange(data, rand)

        if (flag == 12):
            h = binarymuta.Handler()
            return h.Fuzzit(data)

    # 返回值r_code，fuzz报文msg，fuzz测试方法r_flag
    def sdp_random_fuzz(self):
        i = random.randint(0, 4)
        if i == 0:
            return self.fuzz_params()
        if i == 1:
            return self.fuzz_pud_id()
        if i == 2:
            return self.fuzz_parameter_length()
        if i == 3:
            return self.fuzz_transcation_id()
        if i == 4:
            return self.fuzz_all()



if __name__ == '__main__':
    '''
    [0, 7, '\x01', '5\x03\x19\x10\x02\xff\xff5\x00\xff\xff\x00', '\x01\x00\x00\x00\x0f5\x03\x19\x10\x02\xff\xff5\x00\xff\xff\x00']
    [1, 5, '\x06', '59\xcf\x94\x0e\x0c\x8cGI\n\x00\xdf\x93\t\xe4', '\x06\x00\x00\x00\x0f59\xcf\x94\x0e\x0c\x8cGI\n\x00\xdf\x93\t\xe4']
    '''
    addr = '00:0D:47:02:B0:C3'
    s = Sdp(addr)
    msg = '\x06\x00\x00\x00\x0f59\xcf\x94\x0e\x0c\x8cGI\n\x00\xdf\x93\t\xe4'
    for i in range(0, 10):
        print s.send_sdp(msg)
    # for i in range(0, 1000):
    #     print s.fuzz_params()
    # print '************************************************************************************'
    # for i in range(0, 1000):
    #     print s.fuzz_pud_id()
    # print '************************************************************************************'
    # for i in range(0, 1000):
    #     print s.fuzz_parameter_length()
    # print '************************************************************************************'
    # for i in range(0, 1000):
    #     print s.fuzz_transcation_id()
    # print '************************************************************************************'
    # for i in range(0, 1000):
    #     print s.fuzz_all()



